import os
import time
from PySide6.QtCore import Signal, QThread
from adbutils import adb
from tools.tool_box import contains_keywords


class AdbThreadWorker(QThread):
    log_signal = Signal(object)  # 输出Log信号
    connected_signal = Signal()  # 成功连接信号
    disconnect_signal = Signal()  # 断开连接信号

    def __init__(self, fn, *args, **kwargs):
        super().__init__()
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
        self.kwargs["log_signal"] = self.log_signal

    def run(self):
        self.fn(*self.args, **self.kwargs)


class AdbTool:
    def __init__(self):
        self.test_thread = None
        self.__adb_ip = None
        self.__device = None
        self.__is_connected = False  # 连接标志
        self.__should_stop = False  # 停止标志
        self.quit = False  # 线程终止标志
        self.pause_log_setText = None  # 设置暂停按钮文字展示
        self.show_log_setText = None  # 设置连接按钮文字展示
        self.__error_log = []
        # self.__unity_log_cmd = "logcat -v time '*:S Unity:V'"
        self.__unity_log_cmd = "logcat -v time"
        self.__clear_log_cme = "logcat --clear"

    def get_desktop_path(self):
        return os.path.join(os.path.expanduser("~"), "Desktop", f"unity_{int(time.time())}.log.txt")

    def get_error_log(self):
        """
        获取错误日志
        :return: 错误日志字符串文本
        """
        return str.join('', self.__error_log)

    def clear_error_log(self):
        """
        清空错误日志收集器中的内容
        """
        self.__error_log.clear()

    def is_connected(self):
        """
        获取设备连接状态
        :return: 返回设备连接状态
        """
        return self.__is_connected

    def is_same_adb_ip(self, adb_ip):
        """
        判断当前输入设备码是否与已经连接的设备码一致
        :param adb_ip: 当前输入设备码
        :return: 如果一致返回True
        """
        if self.__adb_ip is None:
            return False
        if adb_ip == self.__adb_ip:
            return True
        else:
            return False

    def get_current_adb_ip(self):
        """
        获取当前设备adb_ip
        """
        return self.__adb_ip

    def set_current_adb_ip(self, adb_ip):
        """
        设置当前操作设备adb_ip
        :param adb_ip: 需要连接的 ddb_ip
        """
        self.__adb_ip = adb_ip

    def to_connect(self):
        """
        连接设备并进行相应设置
        """
        self.__is_connected = True
        self.quit = False
        self.show_log_setText("断开设备")

    def end_connect(self):
        """
        断开设备连接并进行相应设置
        """
        self.__is_connected = False
        self.quit = True
        self.show_log_setText("连接设备")

    def pause_log(self):
        """
        暂停打印日志
        """
        self.__should_stop = True
        self.pause_log_setText("打印日志")

    def restart_log(self):
        """
        重新开始打印日志
        """
        self.__should_stop = False
        self.pause_log_setText("暂停日志")

    def get_should_stop(self):
        """
        获取暂停标识
        """
        return self.__should_stop

    def connect(self):
        """
        连接设备
        :return: 返回连接状态，连接成功返回true
        """
        try:
            # 清除旧连接
            if self.__is_connected:
                key, ms = self.disconnect()
                if not key:
                    return False, f"[错误] 存在已经连接的设备，尝试断开连接断开失败: {ms}"
            # 发起新连接
            output = adb.connect(self.__adb_ip, timeout=5)
            if 'cannot' in output:
                return False, f"[错误] 无法连接设备：{output}"
            self.__device = adb.device(self.__adb_ip)
            serial = self.__device.serial
            if serial:
                self.to_connect()
                return True, f"[提示] 成功连接设备: {self.__adb_ip}"
            else:
                self.end_connect()
                return False, f"[错误] 没有可连接设备"
        except ConnectionError as e:
            self.end_connect()
            return False, f"[错误] 设备{self.__adb_ip}，连接失败: {str(e)}"
        except Exception as e:
            return False, f"[错误] 异常: {str(e)}"
        finally:
            self.restart_log()

    def disconnect(self):
        """
        断开设备连接
        :return: 返回连接状态，断开成功返回true
        """
        if not self.__is_connected:
            return True, "[提示] 没有连接设备，无需断开连接"
        try:
            # 强制终止日志流
            self.pause_log()
            # 执行 ADB 断开操作
            ms = adb.disconnect(self.__adb_ip, raise_error=True)
            adb.wait_for(self.__adb_ip, state="disconnect")  # 确保完全断开[4](@ref)
            self.end_connect()
            return True, ms
        except Exception as e:
            return False, f"[错误] 断开异常: {str(e)}"
        finally:
            self.restart_log()
            self.end_connect()

    def show_log(self, log_signal: Signal):
        """
        打印日志
        :param log_signal: 日志打印信号
        """
        try:
            key, ms = self.connect()
            if not key:
                log_signal.emit((1, f"[错误] 设备连接异常：{ms}"))
                return
            log_signal.emit(
                (0, f"[提示] 已连接设备: {self.__device.serial} ({self.__device.prop.get('ro.product.model')})"))
            with self.__device.shell(self.__unity_log_cmd, stream=True) as stream:
                # 添加停止条件检测
                files = stream.conn.makefile(encoding="utf-8", errors="replace")
                while self.__is_connected:
                    while not self.__should_stop:
                        line = files.readline()
                        if not line:
                            continue
                        if contains_keywords(line):
                            log_signal.emit((1, line))
                            self.__error_log.append(line)
                        else:
                            log_signal.emit((0, line))
                        if self.quit:
                            raise
        except BrokenPipeError:
            log_signal.emit((1, "[错误] 日志流中断，可能因清空日志导致"))
        except Exception as e:
            log_signal.emit((1, f"[错误] 日志捕获异常: {str(e)}"))
        finally:
            self.restart_log()
            key, ms = self.disconnect()
            if not key:
                log_signal.emit((1, f"{ms}"))
            else:
                log_signal.emit((0, f"[提示] 断开设备连接，信息：{ms}"))

    # noinspection PyMethodMayBeStatic
    def restart_adb(self):
        """
        重启adb服务
        """
        self.disconnect()
        kill = "adb kill-server&"
        start = "adb start-server&"
        # devices = "adb devices"
        command = f"{kill} {start}"
        output = os.popen(command).read()
        return output

    def clear_log(self):
        """
        清空adb日志
        :return: 返回清空结果，成功返回true
        """
        if not self.__is_connected:
            return False, "[错误] 设备未连接，无法清空日志"
        try:
            self.pause_log()
            ms = self.__device.shell(self.__clear_log_cme)
            self.restart_log()
            return True, f"[提示] 日志已清空: {ms}"
        except Exception as e:
            return False, f"[错误] 清空失败: {str(e)}"

    def skill_adb_server(self):
        """
        保存adb日志
        :return: 返回保存结果，成功返回true
        """
        self.disconnect()
        kill = "adb kill-server"
        output = os.popen(kill).read()
        return output

    # def get_adb_info(self):
    #     output = os.popen("adb devices").read()
    #     # 输出命令的结果
    #     print(output)

# if __name__ == '__main__':
#     d = adb.device()
#
#     print(d.serial)  # 获取序列号
